#include "../include/cache.h"
#include "../include/memory.h"
#include "../include/command.h"
#include "../include/network.h"
#include "../include/threadpool.h"
#include "../include/eviction.h"
#include "../include/storage.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#include <signal.h>
#include <sys/stat.h>

// 全局资源
static NetworkServer* g_server = NULL;
static ThreadPool* g_threadpool = NULL;
static Cache* g_cache = NULL;
static RDBConfig* g_rdb_config = NULL;
// 全局运行标志
static int g_running = 1;

pthread_t save_thread;
int save_running = 0;
//服务器配置
#define PORT 8888
#define IP "0.0.0.0"
#define THREAD_POOL_SIZE 6
#define CACHE_BUCKET_COUNT 1024
#define CACHE_MAX_NODES 2048
#define CACHE_MAX_MEMORY (64*1024*1024)  //64MB

// 保存线程函数
void* save_thread_func(void* arg)
{
    printf("保存线程启动\n");
    while(save_running)
    {
        // 每10秒检查一次
        sleep(10);
        // 获取全局读锁
        pthread_rwlock_rdlock(&g_cache->stats_lock);
        if(rdb_should_save(g_rdb_config, g_cache))
        {
            printf("保存缓存到RDB文件\n");
            rdb_save(g_cache, g_rdb_config->filename);
            g_rdb_config->last_save_time = time(NULL);
            printf("保存成功\n");
        }
        pthread_rwlock_unlock(&g_cache->stats_lock);
    }
    printf("保存线程退出\n");
    return NULL;
}

// 信号处理函数
void signal_handler(int signum)
{
    printf("\n收到信号%d, 正在关闭服务器...\n", signum);
    g_running = 0;
    
    // 强制保存缓存
    if(g_rdb_config && g_cache)
    {
        printf("强制保存缓存到RDB文件\n");
        // 获取全局读锁
        pthread_rwlock_rdlock(&g_cache->stats_lock);
        rdb_save(g_cache, g_rdb_config->filename);
        pthread_rwlock_unlock(&g_cache->stats_lock);
        printf("强制保存成功\n");
    }
    // 停止保存线程
    save_running = 0;
    pthread_join(save_thread, NULL);

    // 打印缓存统计信息
    if(g_cache)
    {
        cache_print_stats(g_cache, "Light Redis");
    }
    
    // 停止网络服务器，清除所有资源
    if(g_server)
    {
        network_server_stop(g_server);
        free(g_server);
        g_server = NULL;
    }
    if(g_threadpool)
    {
        threadpool_destroy(g_threadpool);
        g_threadpool = NULL;
    }
    if(g_cache)
    {
        cache_destroy(g_cache);
        g_cache = NULL;
    }
    // 销毁RDB配置
    if(g_rdb_config)
    {
        rdb_destroy_config(g_rdb_config);
        g_rdb_config = NULL;
    }
    printf("服务器已关闭\n");
    exit(0);
}

// 显示策略选项
void show_strategy_options() 
{
    printf("\n=== 淘汰策略选择 ===\n");
    printf("请选择淘汰策略：\n");
    printf("1. LRU (最近最少使用) - 通用场景\n");
    printf("2. LFU (最少使用) - 内存受限\n");
    printf("3. 随机淘汰 - 随机访问\n");
    printf("4. 近似LRU - 高频访问\n");
    printf("0. 退出\n");
    printf("\n请输入选择 (0-4): ");
}

// 获取用户选择
int get_user_strategy_choice() 
{
    int choice;
    scanf("%d", &choice);
    
    if(choice == 0) {
        printf("退出程序\n");
        exit(0);
    }
    
    if(choice < 1 || choice > 4) {
        printf("无效选择，使用默认策略 (LRU)\n");
        return EVICTION_LRU;
    }
    
    int policies[] = {EVICTION_LRU, EVICTION_LFU, EVICTION_RANDOM, EVICTION_APPROX_LRU};
    int selected = policies[choice - 1];
    
    char* names[] = {"LRU", "LFU", "随机淘汰", "近似LRU"};
    printf("已选择: %s\n", names[choice - 1]);
    
    return selected;
}

int main(int argc, char* argv[])
{
    // 注册信号处理函数
    // 处理 Ctrl+C 信号
    signal(SIGINT, signal_handler);

    printf("Light Redis Server 启动中...\n");
    printf("端口：%d\n", PORT);

    // 选择淘汰策略
    show_strategy_options();
    int eviction_policy = get_user_strategy_choice();

    // 初始化缓存
    g_cache = cache_init(CACHE_BUCKET_COUNT, CACHE_MAX_NODES, CACHE_MAX_MEMORY, eviction_policy);
    if(!g_cache)
    {
        perror("错误：缓存初始化失败");
        return 1;
    }
    
    // 启动过期清理线程
    if(cache_start_cleanup_thread(g_cache) != 0)
    {
        perror("错误：过期清理线程启动失败");
        cache_destroy(g_cache);
        g_cache = NULL;
        return 1;
    }

    // 初始化RDB配置
    g_rdb_config = rdb_init_config("./data/dump.rdb", 300); // 5分钟保存间隔
    if(!g_rdb_config)
    {
        perror("错误：RDB配置初始化失败");
        cache_destroy(g_cache);
        g_cache = NULL;
        return 1;
    }

    // 尝试加载现有RDB文件
    //access 函数用于检查文件是否存在 F_OK 存在返回0，不存在返回-1
    if(access(g_rdb_config->filename, F_OK) == 0)
    {
        printf("发现RDB文件，正在加载...\n");
        if(rdb_load(g_cache, g_rdb_config->filename) == 0)
        {
            printf("RDB文件加载成功\n");
        }
        else
        {
            printf("RDB文件加载失败，使用空缓存\n");
        }
    }

    // 初始化线程池
    g_threadpool = threadpool_create(THREAD_POOL_SIZE);
    if(!g_threadpool)
    {
        perror("错误：线程池初始化失败");
        cache_destroy(g_cache);
        g_cache = NULL;
        return 1;
    }

    // 创建网络服务器
    g_server = (NetworkServer*)malloc(sizeof(NetworkServer));
    g_server->listen_fd = -1;
    g_server->cache = g_cache;
    g_server->epoll_fd = -1;
    g_server->threadpool = g_threadpool;
    g_server->port = PORT;
    
    // 初始化网络服务器
    if(network_server_start(g_server, PORT, g_threadpool, g_cache) != 0)
    {
        perror("错误：网络服务器初始化失败");
        threadpool_destroy(g_threadpool);
        cache_destroy(g_cache);
        free(g_server);
        return 1;
    }

    //启动保存线程
    save_running = 1;
    if(pthread_create(&save_thread, NULL, save_thread_func, NULL) != 0)
    {
        perror("错误：保存线程创建失败");
        network_server_stop(g_server);
        threadpool_destroy(g_threadpool);
        cache_destroy(g_cache);
        rdb_destroy_config(g_rdb_config);
        return 1;
    }

    printf("服务器启动成功，监听端口 %d\n", PORT);
    printf("等待客户连接...\n");
    printf("按 Ctrl+C 关闭服务器\n");

    network_server_run(g_server);

    // 不会走到这里
    printf("服务器已关闭\n");
    return 0;
}